package com.by.rpc.registry;

import com.alibaba.fastjson2.JSON;
import com.by.log.Logger;
import com.by.log.LoggerFactory;
import com.by.rpc.dto.ServiceInstance;
import com.by.rpc.util.KeyUtils;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 基于Redis的服务注册中心实现
 */
public class RedisServiceRegistry implements ServiceRegistry {

    private final Logger logger = LoggerFactory.getLogger(RedisServiceRegistry.class);
    private static final long TTL_SECONDS = 30; // 服务实例TTL为30秒

    private final RedisTemplate<String, Object> redisTemplate;

    public RedisServiceRegistry(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void register(ServiceInstance serviceInstance) {
        String key = KeyUtils.buildServiceKey(serviceInstance.getServiceName(), serviceInstance.getVersion(), serviceInstance.getGroup());
        String field = serviceInstance.getHost() + ":" + serviceInstance.getPort();
        String value = JSON.toJSONString(serviceInstance);

        // 使用Hash结构存储服务实例，field为host:port，value为实例信息
        redisTemplate.opsForHash().put(key, field, value);
        // 设置过期时间
        redisTemplate.expire(key, TTL_SECONDS, TimeUnit.SECONDS);

        logger.info("Registered service instance: {}", serviceInstance);
    }

    @Override
    public void deregister(ServiceInstance serviceInstance) {
        String key = KeyUtils.buildServiceKey(serviceInstance.getServiceName(), serviceInstance.getVersion(), serviceInstance.getGroup());
        String field = serviceInstance.getHost() + ":" + serviceInstance.getPort();

        redisTemplate.opsForHash().delete(key, field);

        logger.info("Deregistered service instance: {}", serviceInstance);
        System.out.println("Deregistered service instance: " + serviceInstance);
    }

    @Override
    public List<ServiceInstance> discover(String key) {
        // 获取所有服务实例
        Set<Object> fields = redisTemplate.opsForHash().keys(key);

        List<ServiceInstance> instances = new ArrayList<>();
        for (Object fieldObj : fields) {
            String field = (String) fieldObj;
            String value = (String) redisTemplate.opsForHash().get(key, field);
            if (value != null) {
                ServiceInstance instance = JSON.parseObject(value, ServiceInstance.class);
                instances.add(instance);
            }
        }

        // 过滤掉已经过期的实例
        long currentTime = System.currentTimeMillis();
        return instances.stream()
                .filter(instance -> currentTime - instance.getRegisterTime() < TTL_SECONDS * 1000)
                .collect(Collectors.toList());
    }

    @Override
    public void updateHeartbeat(ServiceInstance serviceInstance) {
        // 更新心跳其实就是重新注册一次
        register(serviceInstance);
    }

    @Override
    public void registerApiEndpoint(String key, String value, int expireSeconds) {
        // API端点信息持久化存储，不设置过期时间
        if (expireSeconds <= 0) {
            redisTemplate.opsForValue().set(key, value);
        } else {
            redisTemplate.opsForValue().set(key, value, expireSeconds, TimeUnit.SECONDS);
        }
        logger.info("Registered API endpoint: {} -> {}", key, value);
    }

    @Override
    public Map<String, String> discoverApiEndpoints(String pattern) {
        // 注意：Redis的keys命令在生产环境中应谨慎使用，这里仅用于演示
        Set<String> keys = redisTemplate.keys(KeyUtils.RPC_ENDPOINT_SERVICE + KeyUtils.RPC_SPLIT + pattern);
        Map<String, String> result = new HashMap<>();

        for (String key : keys) {
            String value = (String) redisTemplate.opsForValue().get(key);
            if (value != null) {
                // 去掉前缀
                String cleanKey = key.substring((KeyUtils.RPC_ENDPOINT_SERVICE + KeyUtils.RPC_SPLIT).length());
                result.put(cleanKey, value);
                System.out.println("Added endpoint: " + cleanKey + " -> " + value);
            }
        }

        return result;
    }

    @Override
    public Map<String, String> getAllServices() {
        Set<String> keys = redisTemplate.keys(KeyUtils.RPC_ENDPOINT_SERVICE + KeyUtils.RPC_SPLIT + "*");
        Map<String, String> result = new HashMap<>();

        for (String key : keys) {
            String value = (String) redisTemplate.opsForValue().get(key);
            if (value != null) {
                // 去掉前缀
                String cleanKey = key.substring((KeyUtils.RPC_ENDPOINT_SERVICE + KeyUtils.RPC_SPLIT).length());
                result.put(cleanKey, value);
            }
        }

        return result;
    }

    @Override
    public ServiceInstance getInstance(String key) {
        String fullKey = KeyUtils.RPC_ENDPOINT_SERVICE + KeyUtils.RPC_SPLIT + key;
        String value = (String) redisTemplate.opsForValue().get(fullKey);
        if (value != null) {
            // 这里假设存储的是ServiceInstance的JSON字符串
            return JSON.parseObject(value, ServiceInstance.class);
        }
        return null;
    }

    @Override
    public String getApiEndpoint(String key) {
        String fullKey = KeyUtils.RPC_ENDPOINT_SERVICE + KeyUtils.RPC_SPLIT + key;
        return (String) redisTemplate.opsForValue().get(fullKey);
    }

    /**
     * 标记服务为不可用状态
     *
     * @param serviceName    服务名称
     * @param failureCount   失败次数
     * @param timeoutSeconds 超时时间（秒）
     */
    public void markServiceAsUnavailable(String serviceName, int failureCount, int timeoutSeconds) {
        String key = KeyUtils.SERVICE_STATUS_PREFIX + serviceName;
        String value = "unavailable:" + failureCount;
        redisTemplate.opsForValue().set(key, value, timeoutSeconds, TimeUnit.SECONDS);
        System.out.println("Marked service " + serviceName + " as unavailable with failure count " + failureCount);
    }

    /**
     * 检查服务是否可用
     *
     * @param serviceName 服务名称
     * @return 服务是否可用
     */
    public boolean isServiceAvailable(String serviceName) {
        String key = KeyUtils.SERVICE_STATUS_PREFIX + serviceName;
        String value = (String) redisTemplate.opsForValue().get(key);
        return value == null || !value.startsWith("unavailable:");
    }

    /**
     * 获取服务失败次数
     *
     * @param serviceName 服务名称
     * @return 失败次数
     */
    public int getServiceFailureCount(String serviceName) {
        String key = KeyUtils.SERVICE_STATUS_PREFIX + serviceName;
        String value = (String) redisTemplate.opsForValue().get(key);
        if (value != null && value.startsWith("unavailable:")) {
            try {
                return Integer.parseInt(value.substring("unavailable:".length()));
            } catch (NumberFormatException e) {
                return 0;
            }
        }
        return 0;
    }

    /**
     * 清除服务状态标记
     *
     * @param serviceName 服务名称
     */
    public void clearServiceStatus(String serviceName) {
        String key = KeyUtils.SERVICE_STATUS_PREFIX + serviceName;
        redisTemplate.delete(key);
        System.out.println("Cleared service status for " + serviceName);
    }

    @Override
    public void registerInterfaceToService(String field, String value, int expireSeconds) {
        // 添加参数非空检查，避免Redis操作时出现IllegalArgumentException
        if (field == null || value == null) {
            logger.warn("Field or value is null, skipping registration. field: {}, value: {}", field, value);
            return;
        }
        
        String fullKey = KeyUtils.SERVICE_INTERFACE_PREFIX;
        redisTemplate.opsForHash().put(fullKey, field, value);
//        redisTemplate.expire(fullKey, expireSeconds, TimeUnit.SECONDS);
    }

    @Override
    public String getServernameByInterface(String field) {
        return (String) redisTemplate.opsForHash().get(KeyUtils.SERVICE_INTERFACE_PREFIX, field);
    }
}